﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Ivy.Common.Framework.GeneralUtility
{
    public static class StringUtility
    {
        #region Variables & Constants
        // This constant string is used as a "salt" value for the PasswordDeriveBytes function calls. 
        // This size of the IV (in bytes) must = (keysize / 8).  Default keysize is 256, so the IV must be 
        // 32 bytes long.  Using a 16 character string here gives us 32 bytes when converted to a byte array. 
        private const string initCryptoVector = "tu89geji340t89u2";

        // This constant is used to determine the keysize of the encryption algorithm. 
        private const int CryptoKeySize = 256;

        // This constant is used to provide the default PassKey in client app is not supplying.
        private const string CryptoDefaultPassKey = "Ivy";

        #endregion Variables & Constants

        #region Constructor & Destructor
        #endregion Constructor & Destructor

        #region Public Properties
        #endregion Public Properties

        #region Public Methods
        public static string GenerateRandomString(int outPutStringLength)
        {
            string _outPutString = string.Empty;
            int _seedValue = (int)DateTime.Now.Ticks;
            _outPutString = GenerateRandomString(outPutStringLength, _seedValue);
            return _outPutString;
        }
        public static string GenerateRandomString(int outPutStringLength, int seedKey)
        {
            string _outPutString = string.Empty;
            StringBuilder _Strbuilder = new StringBuilder();
            Random _Randomizer = new Random(seedKey);
            char _AsciiChar;
            for (int _loopCounetr = 0; _loopCounetr < outPutStringLength; _loopCounetr++)
            {
                _AsciiChar = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * _Randomizer.NextDouble() + 65)));
                _Strbuilder.Append(_AsciiChar);
            }
            _outPutString = _Strbuilder.ToString();
            return _outPutString;
        }

        public static int GenerateRandomNumber(int minRange, int maxRange)
        {
            int _outPutNumber = 0;
            int _seedValue = (int)DateTime.Now.Ticks;
            _outPutNumber = GenerateRandomNumber(minRange, maxRange, _seedValue);
            return _outPutNumber;
        }
        public static int GenerateRandomNumber(int minRange, int maxRange, int seedKey)
        {
            int _outPutNumber = 0;
            Random _Randomizer = new Random(seedKey);
            _outPutNumber = _Randomizer.Next(minRange, maxRange);
            return _outPutNumber;
        }

        public static int GenerateRandomNumber()
        {
            int _outPutNumber = 0;
            int _seedValue = (int)DateTime.Now.Ticks;
            _outPutNumber = GenerateRandomNumber(_seedValue);
            return _outPutNumber;
        }
        public static int GenerateRandomNumber(int seedKey)
        {
            int _outPutNumber = 0;
            Random _Randomizer = new Random(seedKey);
            _outPutNumber = _Randomizer.Next();
            return _outPutNumber;
        }

        public static string EncryptString(string inPutPlainString)
        {
            string _outPutString = string.Empty;
            string _PassKeyValue = CryptoDefaultPassKey;
            _outPutString = EncryptString(inPutPlainString, _PassKeyValue);
            return _outPutString;
        }
        public static string EncryptString(string inPutPlainString, string passKey)
        {
            string _outPutString = string.Empty;
            byte[] initVectorBytes = Encoding.UTF8.GetBytes(initCryptoVector);
            byte[] plainTextBytes = Encoding.UTF8.GetBytes(inPutPlainString);
            PasswordDeriveBytes password = new PasswordDeriveBytes(passKey, null);
            byte[] keyBytes = password.GetBytes(CryptoKeySize / 8);
            RijndaelManaged symmetricKey = new RijndaelManaged();
            symmetricKey.Mode = CipherMode.CBC;
            ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
            cryptoStream.FlushFinalBlock();
            byte[] cipherTextBytes = memoryStream.ToArray();
            memoryStream.Close();
            cryptoStream.Close();
            _outPutString = Convert.ToBase64String(cipherTextBytes); 
            return _outPutString;
        }

        public static string DecryptString(string inPutEncryptedString)
        {
            string _outPutString = string.Empty;
            string _PassKeyValue = CryptoDefaultPassKey;
            _outPutString = DecryptString(inPutEncryptedString, _PassKeyValue);
            return _outPutString;
        }
        public static string DecryptString(string inPutEncryptedString, string passKey)
        {
            string _outPutString = string.Empty;
            byte[] initVectorBytes = Encoding.ASCII.GetBytes(initCryptoVector);
            byte[] cipherTextBytes = Convert.FromBase64String(inPutEncryptedString);
            PasswordDeriveBytes password = new PasswordDeriveBytes(passKey, null);
            byte[] keyBytes = password.GetBytes(CryptoKeySize / 8);
            RijndaelManaged symmetricKey = new RijndaelManaged();
            symmetricKey.Mode = CipherMode.CBC;
            ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
            MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
            CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
            byte[] plainTextBytes = new byte[cipherTextBytes.Length];
            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
            memoryStream.Close();
            cryptoStream.Close();
            _outPutString = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); 
            return _outPutString;
        }
        #endregion Public Methods

        #region Events
        #endregion Events

        #region Private Methods
        #endregion Private Methods
    }
}
